﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Exceptions;
using Aliyun.Acs.Core.Profile;
using Aliyun.Acs.Dm.Model.V20151123;
using Aliyun.OSS;
using AutoMapper;
using BlogApi.Models;
using BlogApi.ModelsDto;
using BlogApi.MyTool;
using BlogApi.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace BlogApi.Controllers
{
    [Route("api/user")]
    [ApiController]
    public class UserController : ControllerBase
    {
        private readonly IUserRepository _userRepository;
        private readonly IFanRepository _fanRepository;
        private readonly ILikeRepository _likeRepository;
        private readonly IMapper _mapper;

        public UserController(ILikeRepository likeRepository,IFanRepository fanRepository,IUserRepository userRepository,IMapper mapper)
        {
            _userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
            _fanRepository = fanRepository ?? throw new ArgumentNullException(nameof(fanRepository));
            _likeRepository = likeRepository ?? throw new ArgumentNullException(nameof(likeRepository));
            _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
        }
        [HttpPost]
        [Route("registerAcount")]
        public async Task<IActionResult> RegisterUser([FromBody]UserAddDto userAddDto)
        {
            if (await _userRepository.EmailExistsAsync(userAddDto.UserEmail))
            {
                return new JsonResult(new 
                {
                    status="false"
                });
            }
            var userEntity = _mapper.Map<User>(userAddDto);
            _userRepository.AddUser(userEntity);
            if(await _userRepository.SaveAsync())
            {
                return new JsonResult(new { status = "ok" });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpGet]
        [Route("userInfo/{userId}")]
        public async Task<IActionResult> GetUserInfo([FromRoute]Guid userId)
        {
            var exists = await _userRepository.UserExistsAsync(userId);
            if (!exists)
            {
                return NotFound();
            }
            var userEntity = await _userRepository.GetUserAsync(userId);
            var userInfoDto = _mapper.Map<UserInfoDto>(userEntity);
            return new JsonResult(new
            {
                code = 0,
                userInfo = userInfoDto
            });
        }
        [HttpPost]
        [Route("fanAuthor")]
        public async Task<IActionResult> FanAdd([FromBody]FanAddDto fanAddDto)
        {
            var fanEntity = _mapper.Map<Fan>(fanAddDto);
            var userEntity = await _userRepository.GetUserAsync(fanAddDto.AuthorId);
            userEntity.FanNumber++;
            _userRepository.UpdateUser(userEntity);
            _fanRepository.AddFan(fanEntity);
            if(await _fanRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "success",
                    fanNumber = userEntity.FanNumber
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("cancelFanAuthor")]
        public async Task<IActionResult> CancelFan([FromBody]FanDeleteDto fanDeleteDto)
        {
            var fanEntity = await _fanRepository.GetFanAsync(fanDeleteDto.AuthorId, fanDeleteDto.UserId);
            var userEntity = await _userRepository.GetUserAsync(fanDeleteDto.AuthorId);
            userEntity.FanNumber--;
            _userRepository.UpdateUser(userEntity);
            _fanRepository.DeleteFan(fanEntity);
            if(await _fanRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "success",
                    fanNumber = userEntity.FanNumber
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("login")]
        public async Task<IActionResult> Login([FromBody]UserLoginDto userLoginDto)
        {
            var user = await _userRepository.GetUserByEmailAndPasswordAsync(userLoginDto.UserEmail, userLoginDto.Password);
            if (user != null)
            {
                var userInfoDto = _mapper.Map<UserInfoDto>(user);
                return new JsonResult(new
                {
                    verifySuccess = true,
                    userInfo = userInfoDto,
                    token = "test token"
                });
            }
            else
            {
                return new JsonResult(new
                {
                    verifySuccess = false
                });
            }
        }
        [HttpGet]
        [Route("userIsFanAndArticleIsGood/{userId}/{authorId}/{articleId}")]
        public async Task<IActionResult> ExistsFanAndExistsLike([FromRoute]Guid userId,[FromRoute]Guid authorId,[FromRoute]Guid articleId)
        {
            return new JsonResult(new
            {
                userIsFan = await _fanRepository.AuthorUserExistsAsync(authorId, userId),
                articleIsGood = await _likeRepository.UserLikeArticleExistsAsync(articleId, userId)
            });
        }
        [HttpGet]
        [Route("autoLogin/{userId}")]
        public async Task<IActionResult> AutoLogin([FromRoute]Guid userId)
        {
            if(await _userRepository.UserExistsAsync(userId))
            {
                var userInfoDto = _mapper.Map<UserInfoDto>(await _userRepository.GetUserAsync(userId));
                return new JsonResult(new
                {
                    verifySuccess = true,
                    userInfo = userInfoDto,
                    token = "test token"
                });
            }
            else
            {
                return new JsonResult(new
                {
                    verifySuccess = false
                });
            }
        }
        [HttpPost]
        [Route("changeUserInfo")]
        public async Task<IActionResult> UpdateUserInfo([FromBody]UserUpdateDto userUpdateDto)
        {
            var userEntity = await _userRepository.GetUserAsync(userUpdateDto.UserId);
            if (userEntity != null)
            {
                userEntity.NickName = userUpdateDto.UserNickName;
                userEntity.Introduction = userUpdateDto.Description;
                _userRepository.UpdateUser(userEntity);
                if(await _userRepository.SaveAsync())
                {
                    return Ok();
                }
                else
                {
                    return BadRequest();
                }
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("userAvatarUpload/{userId}")]
        [DisableRequestSizeLimit]
        public async Task<IActionResult> UploadUserAvatar([FromRoute]Guid userId,IFormFile file)
        {
            var host = "https://hatsune-miku-yyy-blog-static.oss-cn-chengdu.aliyuncs.com";
            var endpoint = "oss-cn-chengdu.aliyuncs.com";
            var accessKeyId = "LTAI4FdSL1CE3fznDt1JK6bY";
            var accessKeySecret = "GWZYP7S0Fjwv1gdcL72sb9gOAYw1PF";
            var bucketName = "hatsune-miku-yyy-blog-static";
            var objectName = "userImages/"+Tools.GetTimeStamp()+Path.GetExtension(file.FileName);
            var localFilename = file;
            // 创建OssClient实例。
            var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
            try
            {
                // 上传文件。
                var result = client.PutObject(bucketName, objectName, localFilename.OpenReadStream());
                Console.WriteLine("Put object succeeded");
                var userEntity = await _userRepository.GetUserAsync(userId);
                userEntity.UserImageUrl = host + "/" + objectName;
                _userRepository.UpdateUser(userEntity);
                if(await _userRepository.SaveAsync())
                {
                    return new JsonResult(new
                    {
                        status = "ok",
                        imageUrl = host + "/" + objectName
                    });
                }
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception ex)
            {
                Console.WriteLine("Put object failed, {0}", ex.Message);
            }
#pragma warning restore CA1031 // Do not catch general exception types
            return BadRequest();
        }
        [HttpGet]
        [Route("emailVerifyCode/{email}")]
        public IActionResult GetEmailVerifyCode([FromRoute]string email)
        {
            //生成验证码
            var verifyCode = Tools.CreateVerificationText(5);
            //邮件正文部分
            var emailHtml = $"<div><div><img src=\"https://hatsune-miku-yyy-blog-static.oss-cn-chengdu.aliyuncs.com/static/angel1.gif \" alt=\"\" ></div><p style=\"font-size: 30px;\"> 尊敬的用户，您好：</p><p style = \"font-size: 20px;\"> 您的验证码为:<span style=\"font-size: 25px; color: #E9967A;\">{verifyCode}</span>,请不要告诉任何人。</p></div>";
            //Create a client used for initiating a request
            IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", "LTAI4FdSL1CE3fznDt1JK6bY", "GWZYP7S0Fjwv1gdcL72sb9gOAYw1PF");
            IAcsClient client = new DefaultAcsClient(profile);
            SingleSendMailRequest request = new SingleSendMailRequest();
            try
            {
                //Version must set to "2017-06-22" when the regionId is not "cn-hangzhou"
                //request.Version = "2017-06-22";
                request.AccountName = "hatsune_miku_yyy@email.hatsumemikuyyy.top";
                request.FromAlias = "MikuMiku";
                request.AddressType = 1;
                request.TagName = "verifyCode";
                request.ReplyToAddress = true;
                request.ToAddress = email;
                request.Subject = "验证码邮件";
                request.HtmlBody = emailHtml;
                SingleSendMailResponse httpResponse = client.GetAcsResponse(request);
                return new JsonResult(new
                {
                    status = "ok",
                    code = verifyCode
                });
            }
            catch (ServerException e)
            {
                System.Console.WriteLine(e.ToString());
                return BadRequest();
            }
            catch (ClientException e)
            {
                System.Console.WriteLine(e.ToString());
                return BadRequest();
            }
        }
        [HttpGet]
        [Route("emailExists/{email}")]
        public async Task<IActionResult> ExistsUserEmail([FromRoute]string email)
        {
            if (await _userRepository.EmailExistsAsync(email))
            {
                return new JsonResult(new
                {
                    exists=true
                });
            }
            return new JsonResult(new
            {
                exists = false
            });
        }
        [HttpPost]
        [Route("changePassword")]
        public async Task<IActionResult> ChangeUserPassword([FromBody]ChangePasswordDto changePasswordDto)
        {
            var userEntity = await _userRepository.GetUserAsync(changePasswordDto.Email);
            if (userEntity == null)
            {
                return BadRequest();
            }
            userEntity.Password = changePasswordDto.NewPassword;
            _userRepository.UpdateUser(userEntity);
            if(await _userRepository.SaveAsync())
            {
                return Ok();
            }
            return BadRequest();
        }
        [HttpGet]
        [Route("verifyUserPassword/{email}/{password}")]
        public async Task<IActionResult> VerifyPassword([FromRoute]string email,[FromRoute]string password)
        {
            var user = await _userRepository.GetUserByEmailAndPasswordAsync(email, password);
            if (user == null)
            {
                return new JsonResult(new
                {
                    verifySuccess = false
                });
            }
            else
            {
                return new JsonResult(new
                {
                    verifySuccess = true
                });
            }
        }
        [HttpGet]
        [Route("fansList/{authorId}/{index}")]
        public async Task<IActionResult> GetUserFansAsync([FromRoute]Guid authorId,[FromRoute]int index)
        {
            var fanList = await _fanRepository.GetFansByPageAsync(authorId, 20, index);
            List<UserInfoDto> dataList = new List<UserInfoDto>();
            foreach(var item in fanList)
            {
                dataList.Add(_mapper.Map<UserInfoDto>(await _userRepository.GetUserAsync(item.UserId)));
            }
            return new JsonResult(new
            {
                fansList = dataList
            });
        }
    }
}